100. Задача 3n + 1
Рассмотрим следующий
алгоритм:
1. ввести n;
2. вывести n;
3. если n
= 1, то остановиться;
4. если n нечетное, то n = 3 * n + 1;
5. иначе n = n
/ 2;
6. перейти на 2;
При n = 22 будет напечатана следующая последовательность чисел:
22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1. По утверждению
Коллатса приведенный алгоритм всегда остановится для любого значения n. Хотя утверждение до сих пор не доказано. Для заданного n можно определить количество чисел, которое будет напечатано
алгоритмом. Это количество называется длиной цикла. Например, для n = 22 длина цикла равна 16.
В задаче следует найти максимальное значение среди всех длин циклов чисел от i до j включительно.
Вход. Состоит из последовательности целых пар чисел i
и j, каждое из которых больше 0 и меньше 10000. Каждая пара чисел
задается в отдельной строке.
Выход. Для
каждой входной пары чисел i и j вывести ее, а также максимальную
длину цикла среди всех чисел между i и j включительно.
Пример входа
1 10
100 200
201 210
900 1000
Пример
выхода
1 10 20
100 200 125
201 210 89
900 1000
174
РЕШЕНИЕ
элементарные вычисления
Анализ алгоритма
Упорядочим
входные значения i и j (если i > j, то
переставим их местами). Далее для каждого значения k (i £ k £ j) будем
находить длину его цикла. Среди всех длин найдем максимальное значение.
Пример
Рассмотрим
первый тест. Для n = 9 получим последовательность 9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20,
10, 5, 16, 8, 4, 2, 1. Ее длина равна 20 и будет максимально возможной среди всех длин циклов для чисел от 1 до 10.
Реализация алгоритма
Запишем
функцию вычисления максимума двух чисел как макрос:
#define max(a,b) a
> b ? a : b
Функция
cycle_length ищет длину цикла для числа n.
int cycle_length(int n)
{
int cnt;
for(cnt = 1; n != 1; cnt++)
n = (n % 2) ? 3 * n
+ 1: n / 2;
return cnt;
}
Функция
check находит максимальную длину цикла среди всех чисел от i до j.
int check(int
i,int j)
{
int mx = 0;
for(; i <= j; i++)
mx = max (mx,
cycle_length(i));
return mx;
}
Основной
цикл программы. Запомним входные значения i и j в переменных itemp
и jtemp. Если i > j, то переставим их местами. Для
каждой входной пары выводим максимальную длину цикла.
while (scanf("%d
%d",&i,&j) == 2)
{
itemp = i; jtemp = j;
if (i > j) tmp = i, i = j, j = tmp;
printf("%d %d %d\n",itemp, jtemp, check(i,j));
}